#ifndef __GEPFIT_H__
#define __GEPFIT_H__

#include "stdlib.h"
#include "stdio.h"
#include "limits.h"
#include "time.h"
#include "vCL.h"

/*
Acknowledgements:

[1] Gene Expression Programming: a New Adaptive Algorithm for Solving Problems
(Candida Ferreira)

[2] A GPU-Based Implementation of an Enhanced GEP Algorithm 
(Shuai Shao, Xiyang Liu, Mingyuan Zhou, Jiguo Zhan, Xin Liu, Yanli Chu, Hao Chen)
*/

typedef struct pop_struct population;
typedef struct fset_struct fset;
typedef struct train_struct trainingdata;
typedef struct soln_struct solution;
typedef struct term_struct term;

struct train_struct {
	int 	args;
	int 	size;
	float* 	data;
	buffer	B_data;
};

struct fset_struct {
	int 	Fsize;
	int	Tsize;
	char* 	symb;
};

struct pop_struct {
	// POOLS
	char*	poolA;
	char*	poolB;

	// PROPERTIES
	int	length;
	int	genes;
	int	count;
	char* 	pool;
	float*	fitness;

	// RATE PARAMETERS
	float 	mutation_r,
		transIS_r,
		transRIS_r,
		transG_r,
		recombi1_r,
		recombi2_r,
		recombiG_r;

	// GPU BUFFERS
	buffer	B_eval;
	buffer	B_pool;
	buffer 	B_assembly;
	buffer	B_coeffs;
	buffer	B_MLS;
	buffer	B_fitness;
};

struct soln_struct {
	term* 	terms;
	float* 	coeffs;
	int	size;
};

struct term_struct {
	char	expr;
	term* 	L;
	term* 	R;
};

fset setF;
trainingdata trainData;
char scratch[1024];

// INITIALIZATION FUNCTIONS
void loadSets();
char selectF();
char selectT();
char selectS();

// CHROMOSOME FUNCTIONS
char* genChromo(int 	length,
		int	genes,
		char* 	writeTo
		);
void printChromo(int 	length,
		char* 	read
		);
void copyChromo(char* 	srcPool,
		int	srcChro,
		char* 	tgtPool,
		int	tgtChro,
		int 	len
		);

// POPULATION FUNCTIONS
population initPop(int 	length, 	
		int 	count,
		int	genes
		);
void deletePop(population*); 	
void popDump(population*);	 	
void switchPool(population*);		
void loadRateParams(population*);//TODO: file	
void computeFitness(population*); 	
void replicate(population*); 		
void mutate(population*); 	
void transpose(population*); 	//TODO: broken
void recombine(population*); 
void rankSurvivors(population*);//TODO: variable number of survivors, mean error, standard deviation, etc

// SOLUTION FUNCTIONS
solution constructSolution(float* coeffs,
			int 	n_coeffs,
			char* 	chromo,
			int	length
			);
void printSolution_CAS(solution*);

// MISCELLANEOUS FUNCTIONS
int select_noReplace(	int	size
		);

#endif
